﻿using LittleBee.IDAL;
using LittleBee.Cells;
using Newtonsoft.Json.Linq;
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LittleBee.CellStore
{
	class StoreCell : INotifyPropertyChanged
	{
		public bool ChangedFlag = false;

		public DataTable DataTableCellInfo { get; set; }
		public DataTable DataTableCellPointers { get; set; }

		private CodeCompileUnit _codeCompileUnit = new CodeCompileUnit();

		public StoreCell(DataTable dtCellInfo, DataTable dtCellPointers)
		{
			DataTableCellInfo = dtCellInfo;
			DataTableCellPointers = dtCellPointers;
		}

		public event PropertyChangedEventHandler? PropertyChanged;
		private void NotifyPropertyChanged(string propertyName)
		{
			ChangedFlag = true;
			if (PropertyChanged != null)
				PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
		}

		public Int64 CellID
		{
			get
			{
				return DataTableCellInfo.Rows[0].Field<Int64>("cell_id");
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<Int64>("cell_id") != value)
				{
					DataTableCellInfo.Rows[0]["cell_id"] = value;
					NotifyPropertyChanged("cell_id");
				}
			}
		}

		public Int64 StoreID
		{
			get
			{
				return DataTableCellInfo.Rows[0].Field<Int64>("store_id");
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<Int64>("store_id") != value)
				{
					DataTableCellInfo.Rows[0]["store_id"] = value;
					NotifyPropertyChanged("store_id");
				}
			}
		}

		public string CellUUID
		{
			get
			{
				return DataTableCellInfo.Rows[0].Field<string>("cell_uuid")!;
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("cell_uuid") != value)
				{
					DataTableCellInfo.Rows[0]["cell_uuid"] = value;
					NotifyPropertyChanged("cell_uuid");
				}
			}
		}
		public string CellType
		{
			get
			{
				return DataTableCellInfo.Rows[0].Field<string>("type")!;
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("type") != value)
				{
					DataTableCellInfo.Rows[0]["type"] = value;
					NotifyPropertyChanged("type");
				}
			}
		}
		public string CellName
		{
			get
			{
				return DataTableCellInfo.Rows[0].Field<string>("name")!;
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("name") != value)
				{
					DataTableCellInfo.Rows[0]["name"] = value;
					NotifyPropertyChanged("name");
				}
			}
		}
		public string CellDescription
		{
			get
			{
				return DataTableCellInfo.Rows[0].Field<string>("description")!;
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("description") != value)
				{
					DataTableCellInfo.Rows[0]["description"] = value;
					NotifyPropertyChanged("description");
				}
			}
		}

		public string BaseClass
		{
			get
			{
				return DataTableCellInfo.Rows[0].Field<string>("class")!;
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("class") != value)
				{
					DataTableCellInfo.Rows[0]["class"] = value;
					NotifyPropertyChanged("class");
				}
			}
		}

		public JArray Attributes
		{
			get
			{
				return JArray.Parse(DataTableCellInfo.Rows[0].Field<string>(Cell.ATTRIBUTES)!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>(Cell.ATTRIBUTES) != value.ToString())
				{
					DataTableCellInfo.Rows[0][Cell.ATTRIBUTES] = value;
					NotifyPropertyChanged(Cell.ATTRIBUTES);
				}
			}
		}

		public JObject Content
		{
			get
			{
				return JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("content")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("content") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["content"] = value.ToString();
					NotifyPropertyChanged("content");
				}
			}
		}
		public JArray Categories
		{
			get
			{
				return JArray.Parse(DataTableCellInfo.Rows[0].Field<string>("categories")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("categories") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["categories"] = value.ToString();
					NotifyPropertyChanged("categories");
				}
			}
		}
		public JObject Helper
		{
			get
			{
				return JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("helper")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("helper") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["helper"] = value.ToString();
					NotifyPropertyChanged("helper");
				}
			}
		}
		public JObject Revisions
		{
			get
			{
				return JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("revisions")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("revisions") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["revisions"] = value.ToString();
					NotifyPropertyChanged("revisions");
				}
			}
		}

		public JObject CommSet
		{
			get
			{
				return JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("comm_set")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("comm_set") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["comm_set"] = value.ToString();
					NotifyPropertyChanged("comm_set");
				}
			}
		}
		public JObject TransferSet
		{
			get
			{
				return JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("transfer_set")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("transfer_set") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["transfer_set"] = value.ToString();
					NotifyPropertyChanged("transfer_set");
				}
			}
		}
		public JArray Groups
		{
			get
			{
				return JArray.Parse(DataTableCellInfo.Rows[0].Field<string>("groups")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("groups") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["groups"] = value.ToString();
					NotifyPropertyChanged("groups");
				}
			}
		}
		public JObject GroupSet
		{
			get
			{
				return JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("group_set")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("group_set") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["group_set"] = value.ToString();
					NotifyPropertyChanged("group_set");
				}
			}
		}
		public JArray Conditions
		{
			get
			{
				return JArray.Parse(DataTableCellInfo.Rows[0].Field<string>("conditions")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("conditions") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["conditions"] = value.ToString();
					NotifyPropertyChanged("condistions");
				}
			}
		}
		public JObject ConditionSet
		{
			get
			{
				return JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("condition_set")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("condition_set") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["condition_set"] = value.ToString();
					NotifyPropertyChanged("condition_set");
				}
			}
		}
		public JArray Structs
		{
			get
			{
				return JArray.Parse(DataTableCellInfo.Rows[0].Field<string>("structs")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("structs") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["structs"] = value.ToString();
					NotifyPropertyChanged("structs");
				}
			}
		}
		public JObject StructSet
		{
			get
			{
				return JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("struct_set")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("struct_set") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["struct_set"] = value.ToString();
					NotifyPropertyChanged("struct_set");
				}
			}
		}

		public JObject IOPointers
		{
			get
			{
				return JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("io_pointers")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("io_pointers") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["io_pointers"] = value.ToString();
					NotifyPropertyChanged("io_pointers");
				}
			}
		}

		//		public CodeCompileUnit CellCodeCompileUnit
		//		{
		//			get;
		//			set;
		//		}

		public JObject IOSets
		{
			get
			{
				return JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("io_set")!);
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("io_set") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["io_set"] = value.ToString();
					NotifyPropertyChanged("io_set");
				}
			}
		}

		public string CodeOrLibrary
		{
			get
			{
				return DataTableCellInfo.Rows[0].Field<string>("code_or_library")!;
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("code_or_library") != value.ToString())
				{
					DataTableCellInfo.Rows[0]["code_or_library"] = value.ToString();
					NotifyPropertyChanged("code_or_library");
				}
			}
		}

		public string Code
		{
			get
			{
				return DataTableCellInfo.Rows[0].Field<string>("code")!;
			}
			set
			{
				if (DataTableCellInfo.Rows[0].Field<string>("code") != value)
				{
					DataTableCellInfo.Rows[0]["code"] = value;
					NotifyPropertyChanged("code");
				}
			}
		}

		public string Library
		{
			get
			{
				//return DataTableCellInfo.Rows[0].Field<byte[]>("library")!;
				return DataTableCellInfo.Rows[0].Field<string>("library")!;
			}
			set
			{
				//if (System.MemoryExtensions.SequenceEqual(DataTableCellInfo.Rows[0].Field<byte[]>("library").AsSpan<byte>(), value))
				if (DataTableCellInfo.Rows[0].Field<string>("library") != value)
				{
					DataTableCellInfo.Rows[0]["library"] = value;
					NotifyPropertyChanged("library");
				}
			}
		}

		public static Dictionary<string, string> BaseTypes = new Dictionary<string, string>()
		{
			{ "bool", "bool" },
			{ "sbyte", "sbyte" },
			{ "short", "short" },
			{ "int", "int" },
			{ "long", "long" },
			{ "byte", "byte" },
			{ "ushort", "ushort" },
			{ "uint", "uint" },
			{ "ulong", "ulong" },
			{ "decimal", "decimal" },
			{ "float", "float" },
			{ "double", "double" },
			{ "string", "string" },
			{ "bin", "bin" },
			{ "datetime", "datetime" },
			{ "timespan", "timespan" },
			{ "eu", "eu" },
			{ "list", "list" },
			{ "map", "map" },
		};

		public Dictionary<string, string> GetStructTypes()
		{
			Dictionary<string, string> dctStructTypes = new Dictionary<string, string>();

			foreach (var item in Structs)
			{
				dctStructTypes[item.ToString()] = item.ToString();
			}

			return dctStructTypes;
		}

		//private string GenerateCellCode()
		//{
		//	CellCodeGenerator code = new CellCodeGenerator
		//	{
		//		CellType = CellType,
		//		CellBaseClass = BaseClass
		//	};

		//	return code.GeneratedCode();
		//}

		internal void Save()
		{
			ChangedFlag = false;
			LBAccess.Instance.StoreUpdateCellInfo(DataTableCellInfo);
			LBAccess.Instance.StoreUpdateCellPointers(DataTableCellPointers);
		}

		internal JObject GetCellExportInfo()
		{

			JObject joRet = new JObject();

			JObject joCellInfo = new JObject
			{
				["cell_uuid"] = DataTableCellInfo.Rows[0].Field<string>("cell_uuid"),
				["type"] = DataTableCellInfo.Rows[0].Field<string>("type"),
				["name"] = DataTableCellInfo.Rows[0].Field<string>("name"),
				["description"] = DataTableCellInfo.Rows[0].Field<string>("description"),
				["class"] = DataTableCellInfo.Rows[0].Field<string>("class"),
				["attributes"] = JArray.Parse(DataTableCellInfo.Rows[0].Field<string>("attributes")!),
				["content"] = JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("content")!),
				["categories"] = JArray.Parse(DataTableCellInfo.Rows[0].Field<string>("categories")!),
				["helper"] = JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("helper")!),
				["revisions"] = JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("revisions")!),
				["comm_set"] = JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("comm_set")!),
				["transfer_set"] = JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("transfer_set")!),
				["groups"] = JArray.Parse(DataTableCellInfo.Rows[0].Field<string>("groups")!),
				["group_set"] = JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("group_set")!),
				["conditions"] = JArray.Parse(DataTableCellInfo.Rows[0].Field<string>("conditions")!),
				["condition_set"] = JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("condition_set")!),
				["structs"] = JArray.Parse(DataTableCellInfo.Rows[0].Field<string>("structs")!),
				["struct_set"] = JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("struct_set")!),
				["io_pointers"] = JArray.Parse(DataTableCellInfo.Rows[0].Field<string>("io_pointers")!),
				["io_set"] = JObject.Parse(DataTableCellInfo.Rows[0].Field<string>("io_set")!),
				["code_or_library"] = DataTableCellInfo.Rows[0].Field<string>("code_or_library"),
				["code"] = DataTableCellInfo.Rows[0].Field<string>("code"),
				["library"] = DataTableCellInfo.Rows[0].Field<string>("library")!,
			};
			joRet["cell_info"] = joCellInfo;

			JArray jaPointers = new JArray();
			foreach (DataRow item in DataTableCellPointers.Rows)
			{
				JObject joPointer = new JObject
				{
					["pid"] = item.Field<string>("pid"),
					["name"] = item.Field<string>("name"),
					["description"] = item.Field<string>("description"),
					["attribute"] = item.Field<UInt64>("attribute"),
					["type"] = item.Field<string>("type"),
					["value"] = JObject.Parse(item.Field<string>("value")!),
					["helper"] = JObject.Parse(item.Field<string>("helper")!)
				};

				jaPointers.Add(joPointer);
			}
			joRet["pointers"] = jaPointers;

			return joRet;
		}
	}
}
